package com.evil.common.core.entity;

import com.alibaba.fastjson.JSON;
import com.evil.common.core.constant.AppConstant;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

@Data
@NoArgsConstructor
public final class QueryModel<T> {

    private int pageNum = AppConstant.DEFAULT_PAGE;
    private int pageSize = AppConstant.DEFAULT_PAGE_SIZE;
    @Valid
    private T param;
    @Valid
    private List<Order> orders = new ArrayList<>();

    public QueryModel(T param) {
        this.param = param;
    }

    public QueryModel(int pageNum, int pageSize, T param) {
        this.pageNum = pageNum;
        this.pageSize = pageSize;
        this.param = param;
    }

    public QueryModel(QueryModel<?> queryModel, T t) {
        this.pageNum = queryModel.getPageNum();
        this.pageSize = queryModel.getPageSize();
        this.param = t;
        this.orders = queryModel.getOrders();
    }

    public QueryModel<T> addOrders(Order... orders) {
        this.orders.addAll(Arrays.asList(orders));
        return this;
    }

    public void setPageNum(int pageNum) {
        this.pageNum = pageNum <= 0 ? AppConstant.DEFAULT_PAGE : pageNum;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize <= 0 ? AppConstant.DEFAULT_PAGE_SIZE : pageSize;
    }

    public Optional<T> getCheckParam() {
        return Optional.ofNullable(param);
    }

    public boolean hasOrders() {
        return !orders.isEmpty();
    }

    public String initOrder() {
        return StringUtils.join(this.orders, ", ");
    }

    public int getStartIndex() {
        return (pageNum - 1) * pageSize;
    }

    public int getEndIndex() {
        return pageNum * pageSize;
    }

    public <K> QueryModel<K> trans(K k) {
        QueryModel<K> qm = new QueryModel<>();
        qm.setPageNum(this.pageNum);
        qm.setPageSize(this.pageSize);
        qm.setOrders(this.orders);
        qm.setParam(k);
        return qm;
    }

    @Override
    public String toString() {
        return JSON.toJSONString(this);
    }
}

